import matplotlib
import numpy as np
import matplotlib.pyplot as plt

# 设置 matplotlib 支持中文显示
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 'SimHei' 是一种常见的中文黑体字体
matplotlib.rcParams['axes.unicode_minus'] = False  # 正确显示负号

def ObjFun(ttt, id):
    n1, n2 = 100, 100
    maa = [
        [0.1, 4, 2, 0.1, 18, 3, 0.1, 6, 3, 56, 6, 5],
        [0.2, 4, 2, 0.2, 18, 3, 0.2, 6, 3, 56, 6, 5],
        [0.1, 4, 2, 0.1, 18, 3, 0.1, 6, 3, 56, 30, 5],
        [0.2, 4, 1, 0.2, 18, 1, 0.2, 6, 2, 56, 30, 5],
        [0.1, 4, 8, 0.2, 18, 1, 0.1, 6, 2, 56, 10, 5],
        [0.05, 4, 2, 0.05, 18, 3, 0.05, 6, 3, 56, 10, 40]
    ]
    a, b, c = maa[id][0:3]
    a1, b1, c1 = maa[id][3:6]
    a2, b2, c2, d2 = maa[id][6:10]
    a3, b3 = maa[id][10:12]
    ce1, ce2, ce3, ce4 = ttt
    D = min(n1 * ce1 * (1 - a) + n1 * (1 - ce1), n2 * ce2 * (1 - a1) + n2 * (1 - ce2))
    beta = a + a1 + a2 - a * a1 - a * a2 - a1 * a2 + a * a1 * a2
    inco = D * ce3 * (1 - beta) + D * (1 - ce3) * beta
    mon = n1 * b + n2 * b1 + n1 * ce1 * c + n2 * ce2 * c1 + D * b2 + D * ce3 * c2 + D * (1 - ce3) * a3 * beta + D * beta * ce4 * b3
    nn = D * beta * ce4
    DD = min(nn * ce1 * (1 - a) + nn * (1 - ce1), nn * ce2 * (1 - a1) + nn * (1 - ce2))
    mon += nn * (ce1 * c + ce2 * c) + DD * b2 + DD * ce3 * c2
    inco += DD * ce3 * (1 - beta) + DD * (1 - ce3) * beta
    return mon - inco

def main():
    jingyushu = 20
    MAXGEN = 200
    weidu = 4
    ub = np.ones(weidu)
    lb = np.zeros(weidu)
    L_p = np.zeros(weidu)
    id = 4
    L_s = float('inf')
    PS = np.random.rand(jingyushu, weidu) * (ub - lb) + lb
    trace = np.zeros(MAXGEN)
    specific_points = [0, 25, 50, 75, 100, 125, 150, 175, 200]
    specific_values = {point: None for point in specific_points}

    for kk in range(MAXGEN):
        for i in range(jingyushu):
            PS[i, (PS[i, :] > ub)] = ub[PS[i, :] > ub]
            PS[i, (PS[i, :] < lb)] = lb[PS[i, :] < lb]
            fitness = ObjFun(PS[i, :], id)
            if fitness < L_s:
                L_s = fitness
                L_p = PS[i, :].copy()
        if kk in specific_points:
            specific_values[kk] = L_s
        a = 2 - kk * 2 / MAXGEN
        a2 = -1 - kk / MAXGEN
        for i in range(jingyushu):
            r1, r2 = np.random.rand(2)
            A = 2 * a * r1 - a
            C = 2 * r2
            b = 1
            l = (a2 - 1) * np.random.rand() + 1
            p = np.random.rand()
            pmutation = np.sin(np.pi / 3 + np.pi * kk / (6 * MAXGEN))
            for j in range(weidu):
                if p < pmutation:
                    if abs(A) >= 1:
                        rand_leader_index = np.random.randint(jingyushu)
                        X_r = PS[rand_leader_index, :]
                        D_x_r = abs(C * X_r[j] - PS[i, j])
                        PS[i, j] = X_r[j] - A * D_x_r
                    elif abs(A) < 1:
                        D_L = abs(C * L_p[j] - PS[i, j])
                        PS[i, j] = L_p[j] - A * D_L
                else:
                    distance_Leader = abs(L_p[j] - PS[i, j])
                    PS[i, j] = distance_Leader * np.exp(b * l) * np.cos(l * 2 * np.pi) + L_p[j]
        trace[kk] = L_s

    plt.plot(trace, linewidth=2)
    plt.xlabel('迭代次数')
    plt.ylabel('适应度值')
    plt.title('适应度曲线')
    plt.legend()
    plt.grid(True)
    plt.show()

    print(f"情况：{id}\n")
    print('答案:', L_p)
    print(f"代价：{L_s}")
    print("特定迭代次数的适应度值：")
    for point in specific_points:
        print(f"迭代次数 {point}: 适应度值 {specific_values[point]}")

if __name__ == "__main__":
    main()